﻿// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2023 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

using Abc.Utils;
using Furion;
using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System.Linq.Expressions;

namespace Abc.EntityFramework.Core;

[AppDbContext("ConnectionString")]
public class DefaultDbContext : AppDbContext<DefaultDbContext>, IModelBuilderFilter
{
    /// <summary>
    ///     设置最小日期时间
    /// </summary>
    private readonly DateTimeOffset minDateTimeOffset = Convert.ToDateTime("1900-01-01");

    public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)
    {
        EnabledEntityChangedListener = true; //启用实体数据更改监听
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // optionsBuilder.UseExceptionProcessor();
        base.OnConfiguring(optionsBuilder);
    }

    protected override void SaveChangesFailedEvent(DbContextErrorEventData eventData)
    {
        base.SaveChangesFailedEvent(eventData);
    }

    protected override void SavedChangesEvent(SaveChangesCompletedEventData eventData, int result)
    {
        base.SavedChangesEvent(eventData, result);
    }

    /// <summary>
    ///     重写保存之前事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result)
    {
        // 获取当前事件对应上下文
        var dbContext = eventData.Context;
        // 强制重新检查一边实体更改信息
        dbContext!.ChangeTracker.DetectChanges();

        // 通过请求中获取当前操作人
        var userId = App.HttpContext.GetValue<int>(ClaimConst.Claim_UserId); //
        var userName = App.HttpContext.GetValue<string>(ClaimConst.Claim_Name); //

        // 获取所有新增和更新的实体
        var entities = dbContext.ChangeTracker.Entries().Where(u =>

//u.Entity.GetType() != typeof(SysLogAudit) && u.Entity.GetType() != typeof(SysLogOp) && u.Entity.GetType() != typeof(SysLogVisit) && u.Entity.GetType() != typeof(SysLog) &&
            u.State == EntityState.Added || u.State == EntityState.Modified || u.State == EntityState.Deleted);

        //审计日志
        //AutidLog(eventData, userId, userName);

        #region 创建人、最后操作人

        {
            //// 获取所有新增和更新的实体
            //var entities = dbContext.ChangeTracker.Entries().Where(u => u.State == EntityState.Added || u.State == EntityState.Modified);

            //foreach (var entity in entities)
            //{
            //    switch (entity.State)
            //    {
            //        // 自动设置租户Id
            //        case EntityState.Added:
            //            entity.Property(nameof(CreateEntity.CreatorUserId)).CurrentValue = userId ?? 0;
            //            entity.Property(nameof(CreateEntity.CreatorUserName)).CurrentValue = userName;
            //            entity.Property(nameof(CreateEntity.CreationTime)).CurrentValue = DateTime.Now;
            //            break;
            //        // 排除租户Id
            //        case EntityState.Modified:
            //            entity.Property(nameof(Entity.TenantId)).IsModified = false;

            //            entity.Property(nameof(FullEntity.LastModifierUserId)).CurrentValue = userId ?? 0;
            //            entity.Property(nameof(FullEntity.LastModifierUserName)).CurrentValue = userName;
            //            entity.Property(nameof(FullEntity.LastModificationTime)).CurrentValue = DateTime.Now;

            //            break;
            //    }
            //}

            //子实体被修改的时候，去这里找旧的值，这样就不用去数据库再找一遍了
            //var deletedcache = entities.Where(d => d.State == EntityState.Deleted).ToDictionary(d => d.Entity.GetType().FullName + d.Property("Id").CurrentValue, d => d);
            foreach (var entity in entities)
                switch (entity.State)
                {
                    case EntityState.Added:
                    {
                        //if (entity.Entity is not ICreate creationtimeentity) continue;
                        //if (!entity.Entity.GetType().IsSubclassOf(typeof(ICreate))) continue;
                        if (entity.Entity is ICreate creationtimeentity)
                        {
                            //var creationtimeentity = entity as ICreate;
                            //判断创建时间是否小于 定义的最小日期时间，如果是则设置为当前时间
                            //主要是为了方便有特殊需求需要设置创建时间的情况
                            if (creationtimeentity.CreationTime < minDateTimeOffset)
                                creationtimeentity.CreationTime = DateTimeOffset.Now;
                            creationtimeentity.CreatorUserId = userId;
                            creationtimeentity.CreatorUserName = userName!;
                        }
                    }

                        break;

                    case EntityState.Modified:

                    {
                        if (entity.Entity is IDeleted deleted)
                        {
                            //判断是否是软删除/假删除  如果是假删除 设置删除信息
                            var isdeleted = entity.Property(nameof(IDeleted.IsDeleted)).CurrentValue;
                            if ((bool)isdeleted)
                            {
                                deleted.DeletedTime = DateTimeOffset.Now;
                                deleted.DeletedUserId = userId;
                                deleted.DeletedUserName = userName;
                            }
                            else
                            {
                                //如果是更新，更新信息
                                if (entity.Entity is IUpdate updatetimeentity)
                                {
                                    updatetimeentity.UpdateTime = DateTimeOffset.Now;
                                    updatetimeentity.UpdateUserId = userId;
                                    updatetimeentity.UpdateUserName = userName;
                                }
                            }
                        }
                        else
                        {
                            //如果是更新，更新信息
                            if (entity.Entity is IUpdate updatetimeentity)
                            {
                                updatetimeentity.UpdateTime = DateTimeOffset.Now;
                                updatetimeentity.UpdateUserId = userId;
                                updatetimeentity.UpdateUserName = userName;
                            }
                        }

                        if (entity.Entity is ICreate create)
                        {
                            // 排除创建人
                            entity.Property(nameof(FullEntity.CreatorUserId)).IsModified = false;
                            entity.Property(nameof(FullEntity.CreatorUserName)).IsModified = false;
                            // 排除创建日期
                            entity.Property(nameof(FullEntity.CreationTime)).IsModified = false;
                        }
                    }
                        break;

                    case EntityState.Deleted:
                        // entity.Property(nameof(FullEntity.DeletionTime)).CurrentValue = DateTime.Now ;
                        //这个是物理删除，不做处理
                        break;
                }
        }

        #endregion 创建人、最后操作人

        base.SavingChangesEvent(eventData, result);
    }

    //public DbSet<SysLogAudit> AutidLogs { get; set; }

    #region 全局筛选器

    /// <summary>
    ///     构建之后
    /// </summary>
    /// <param name="modelBuilder"></param>
    /// <param name="entityBuilder"></param>
    /// <param name="dbContext"></param>
    /// <param name="dbContextLocator"></param>
    public void OnCreated(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext,
        Type dbContextLocator)
    {
        var expression = BuilderIsDeleteLambdaExpression(entityBuilder);
        if (expression == null) return;

        entityBuilder.HasQueryFilter(expression);
    }

    /// <summary>
    ///     构建之前
    /// </summary>
    /// <param name="modelBuilder"></param>
    /// <param name="entityBuilder"></param>
    /// <param name="dbContext"></param>
    /// <param name="dbContextLocator"></param>
    public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext,
        Type dbContextLocator)
    {
    }

    /// <summary>
    ///     构建 u => EF.Property<bool>(u, "IsDeleted") == false 表达式
    /// </summary>
    /// <param name="entityBuilder"></param>
    /// <returns></returns>
    private LambdaExpression BuilderIsDeleteLambdaExpression(EntityTypeBuilder entityBuilder)
    {
        // 获取实体构建器元数据
        var metadata = entityBuilder.Metadata;
        if (metadata.FindProperty(nameof(FullEntity.IsDeleted)) == null) return default;

        // 创建表达式元素
        var parameter = Expression.Parameter(metadata.ClrType, "u");
        var properyName = Expression.Constant(nameof(FullEntity.IsDeleted));
        var propertyValue = Expression.Constant(false);

        // 构建表达式 u => EF.Property<bool>(u, "IsDeleted") == false
        var expressionBody =
            Expression.Equal(
                Expression.Call(typeof(EF), nameof(EF.Property), new[] { typeof(bool) }, parameter, properyName),
                propertyValue);
        var expression = Expression.Lambda(expressionBody, parameter);
        return expression;
    }

    #endregion 全局筛选器

    ///// <summary>
    ///// 审计日志
    ///// </summary>
    ///// <param name="eventData"></param>
    ///// <param name="entities"></param>
    ///// <param name="userId"></param>
    ///// <param name="userName"></param>
    //private void AutidLog(DbContextEventData eventData, int userId, string userName)
    //{
    //    #region 审计日志
    //    {
    //        try
    //        {
    //            var entities = eventData.Context.ChangeTracker.Entries().Where(u =>
    //          u.Entity.GetType() != typeof(SysLogAudit) && u.Entity.GetType() != typeof(SysLogOp) && u.Entity.GetType() != typeof(SysLogVisit) &&
    //          (u.State == EntityState.Added || u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Detached));

    //            // 获取所有更改，删除，新增的实体，但排除审计实体（避免死循环）
    //            //var entities = dbContext.ChangeTracker.Entries()
    //            //    .Where(u => u.Entity.GetType() != typeof(AutidLog) && (u.State == EntityState.Modified ||
    //            //                                                           u.State == EntityState.Deleted ||
    //            //                                                           u.State == EntityState.Added))
    //            //    .ToList();
    //            var autidlogs = new List<SysLogAudit>();
    //            var changecontent = new StringBuilder();
    //            // 获取所有已更改的实体
    //            foreach (var entity in entities)
    //            {
    //                // 获取实体类型
    //                var entityType = entity.Entity.GetType();

    //                // 获取所有实体有效属性，排除 [NotMapper] 属性
    //                var props = entity.OriginalValues.Properties;

    //                // 获取实体当前（现在）的值
    //                var currentValues = entity.CurrentValues;

    //                // 获取数据库中实体的值
    //                var databaseValues = entity.GetDatabaseValues();

    //                //获取主键的值
    //                var key = props.FirstOrDefault(o => o.IsPrimaryKey())?.Name;
    //                var keyvalue = currentValues?[key] ?? "";

    //                changecontent.Clear();//遍历前清空
    //                                      // 遍历所有属性
    //                foreach (var prop in props)
    //                {
    //                    // 获取属性名
    //                    var propName = prop.Name;
    //                    // 获取现在的实体值
    //                    var newValue = currentValues[propName];
    //                    object oldValue = null;
    //                    // 如果是新增数据，则 databaseValues 为空，所以需要判断一下
    //                    if (databaseValues != null)
    //                    {
    //                        oldValue = databaseValues[propName];
    //                    }
    //                    //if (newValue == oldValue) continue;
    //                    //if ( newValue.Equals(oldValue)) continue;
    //                    if (newValue == oldValue) continue;

    //                    changecontent.AppendLine($"{propName}: 【{oldValue?.ToString()}】 =>  【{newValue?.ToString()}】");
    //                }

    //                var autidlog = new SysLogAudit
    //                {
    //                    DataId = keyvalue.ToString(),
    //                    Table = entityType.Name, // 表名
    //                                             //Column = propName, // 更新的列
    //                                             //NewValue = newValue?.ToString(), // 新值
    //                                             //OldValue = oldValue?.ToString(), // 旧值
    //                    Content = changecontent.ToString(),
    //                    CreationTime = DateTime.Now, // 操作时间
    //                    CreatorUserId = userId, // 操作人
    //                    CreatorUserName = userName,
    //                    Operate = entity.State.GetEntityState() // 操作方式：新增、更新、删除
    //                };
    //                autidlogs.Add(autidlog);
    //            }
    //            // 插入审计日志表
    //            eventData.Context.Set<SysLogAudit>().AddRange(autidlogs);
    //        }
    //        catch (Exception ex)
    //        {
    //        }
    //    }

    //    #endregion 审计日志
    //}
}